package cc.co.taciano.agenda2.dao;

import cc.co.taciano.agenda2.beans.Bean;
import cc.co.taciano.agenda2.dao.util.DataAccessLayerException;
import cc.co.taciano.agenda2.dao.util.HibernateFactory;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

public abstract class AbstractDao<T extends Bean> {

    protected Session session;
    protected Transaction tx;

    public AbstractDao() {
        HibernateFactory.buildIfNeeded();
    }

    protected void saveOrUpdate(T obj) throws DataAccessLayerException {
        try {
            session = HibernateFactory.openSession();
            tx = session.beginTransaction();
            session.saveOrUpdate(obj);
            tx.commit();
        } catch (HibernateException e) {
            HibernateFactory.rollback(tx);
            throw new DataAccessLayerException(e);
        } finally {
            HibernateFactory.close(session);
        }
    }

    protected void delete(T obj) throws DataAccessLayerException {
        try {
            session = HibernateFactory.openSession();
            tx = session.beginTransaction();
            session.delete(obj);
            tx.commit();
        } catch (HibernateException e) {
            HibernateFactory.rollback(tx);
            throw new DataAccessLayerException(e);
        } finally {
            HibernateFactory.close(session);
        }
    }

    /**
     * @param clazz
     * @param id
     */
    protected void delete(Class<T> clazz, Integer id) throws DataAccessLayerException {
        Object obj = null;
        try {
            session = HibernateFactory.openSession();
            tx = session.beginTransaction();
            obj = session.get(clazz, id);
            session.delete(obj);
            tx.commit();
        } catch (HibernateException e) {
            HibernateFactory.rollback(tx);
            throw new DataAccessLayerException(e);
        } finally {
            HibernateFactory.close(session);
        }
    }

    protected Object find(Class<T> clazz, Integer id) throws DataAccessLayerException {
        Object obj = null;
        try {
            session = HibernateFactory.openSession();
            tx = session.beginTransaction();
            obj = session.get(clazz, id);
            tx.commit();
        } catch (HibernateException e) {
            HibernateFactory.rollback(tx);
            throw new DataAccessLayerException(e);
        } finally {
            HibernateFactory.close(session);
        }
        return obj;
    }

    @SuppressWarnings("unchecked")
    protected List<T> findAll(Class<T> clazz) throws DataAccessLayerException {
        List<T> objects = null;
        try {
            session = HibernateFactory.openSession();
            tx = session.beginTransaction();
            Query query = session.createQuery("from " + clazz.getName());
            objects = query.list();
            tx.commit();
        } catch (HibernateException e) {
            HibernateFactory.rollback(tx);
            throw new DataAccessLayerException(e);
        } finally {
            HibernateFactory.close(session);
        }
        return objects;
    }
}
